#ifndef _WINDLL
#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>
#include <filesystem>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
#include <libavutil/pixfmt.h>
//#include <opencv2/gapi.hpp>
//#include <vld.h>

#include <thread>
#include "DHVideo.h"

enum AVPixelFormat;
enum AVHWDeviceType;
extern int n_hw_accels;
extern AVPixelFormat g_format;
extern AVHWDeviceType hwtype;
extern void test_start();
extern double test_check();

int channel = 3;
void setchannel()
{
	switch(g_format)
	{
		case AV_PIX_FMT_GRAY8:
			channel=1;break;
		case AV_PIX_FMT_RGB24:
			channel=3;break;
		case AV_PIX_FMT_BGR24:
			channel=3;break;
		case AV_PIX_FMT_ARGB:
			channel=4;break;
		case AV_PIX_FMT_RGBA:
			channel=4;break;
		default:break;
	}
}
void generateBitmap(cv::Mat& img,int i)
{
	for (int y = 0; y < img.cols; y++) {
		for (int x = 0; x < img.rows; x++) {
			switch(g_format)
			{
				case AV_PIX_FMT_GRAY8:
					img.at<uchar>(x,y) = (x + (y + i) * 3)%255;break;
				case AV_PIX_FMT_RGB24:
					img.at<cv::Vec3b>(x,y) = cv::Vec3b(x + y + i * 3,128 + y + i * 2, 64 + x + i * 5);break;
				case AV_PIX_FMT_BGR24:
					img.at<cv::Vec3b>(x,y) = cv::Vec3b(64 + x + i * 5,128 + y + i * 2,x + y + i * 3);break;
				case AV_PIX_FMT_ARGB:
					img.at<cv::Vec4b>(x,y) = cv::Vec4b(255,x + y + i * 3,128 + y + i * 2, 64 + x + i * 5);break;
				case AV_PIX_FMT_RGBA:
					img.at<cv::Vec4b>(x,y) = cv::Vec4b(x + y + i * 3,128 + y + i * 2, 64 + x + i * 5,255);break;
				default:break;
			}
		}
	}
	//cv::imwrite("encode.bmp",img);
}
const int width = 1920, height = 1080;
void save_picture(void* data,int len)
{
	cv::Mat mat = cv::Mat(height,width,CV_8UC(channel),data);
	//cv::cvtColor(mat, mat, cv::COLOR_YUV2BGR);
	cv::imwrite("test.bmp",mat); 
}
int index = 0;
FILE* fl = nullptr;
bool bEncodeX264 = false;
int main(int argc, char** argv)
{
	int timesec = 4;
	int framerate = 80;
	int bitrate = width*height;
	SetBitmapFormat(8);
	setchannel();
	SetLogDisplay(true);
	std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
	if(argc<3)	printf("error: no input\r\n");
	if(argc>3)  bEncodeX264 = (std::atoi(argv[2])==1?true:false);
	if(argc>3)  n_hw_accels = std::atoi(argv[3]);
	if(strcmp(argv[1],"1")==0)
	{
		#pragma region 合并
		std::string file1 = "D:\\DH_Work\\兰州地铁1号线\\20201105_兰州1号线\\104706_1\\15西站什字站\\视频\\20200923053847175_0.mp4";
		std::string file2 = "D:\\DH_Work\\兰州地铁1号线\\20201105_兰州1号线\\104706_1\\15西站什字站\\视频\\20200923053847176_0.mp4";
		std::string out_file = "D:\\DH_Work\\兰州地铁1号线\\20201105_兰州1号线\\104706_1\\15西站什字站\\视频\\out.mp4";
		//while (true)
		{
			void *pHandle = nullptr;
			__int64 time1 = GetFileTimeSpan(file1.c_str());
			__int64 time2 = GetFileTimeSpan(file2.c_str());
			BeginSplitFile(&pHandle, file1.c_str(), out_file.c_str());
			SplitFile(&pHandle, 0, time1 / 10.0);
			BeginSplitFile(&pHandle, file2.c_str(), out_file.c_str());
			SplitFile(&pHandle, 0, time2 / 10.0);
			EndSplitFile(&pHandle);
			EndSplitFile(&pHandle);
		}
		#pragma endregion
	}
	else if(strcmp(argv[1],"2")==0)
	{
		#pragma region 压缩
        index = 0;
        void *pHandle = nullptr;
		fl = fopen(bEncodeX264?"encode.h264":"encode.h265", "wb+");
		cv::Mat image = cv::Mat::zeros(height,width,CV_8UC(channel));
		BeginEncode(&pHandle,nullptr,width,height,framerate,bitrate,bEncodeX264?27:173,[](void* obj, unsigned char* data, int& len){
			static int i=0;
			printf("------------%d\r\n",i++);
			fwrite(data,1,len,fl);
			fflush(stdout);
		});
		
		for(int i=0;i<framerate*timesec;i++){
			std::string file = std::string("img\\image_")+std::to_string(i%100)+std::string(".bmp");
			cv::Mat img = cv::imread(file.c_str(),-1);
			if(i==0) printf("-------%d channel \r\n",img.channels());
			if(img.dims == 0 || img.channels() != channel) {
				printf("############");
				generateBitmap(image,i);
				ImageEncode(&pHandle,image.data,image.cols*image.rows*image.elemSize());
			}else{
				ImageEncode(&pHandle,img.data,img.cols*img.rows*img.elemSize());
			}
		}
		EndEncode(&pHandle);

		std::this_thread::sleep_for(std::chrono::seconds(10));
		//muxing file
		pHandle=nullptr;
		unsigned char buf[1024];
		fseek(fl,0,0);
		BeginMuxing(&pHandle,"encode.mp4",width,height,framerate,bitrate,bEncodeX264?27:173,false);
		while(feof(fl)==0){
			int rlen = fread(buf,1,1024,fl);
			//std::this_thread::sleep_for(std::chrono::milliseconds(rand()%200));
			Muxing(&pHandle,buf,1024);
		}
		EndMuxing(&pHandle);
		printf("-------file finish \r\n");
		fclose(fl);
		#pragma endregion
	}
	else if(strcmp(argv[1],"3")==0)
	{
		#pragma region 解压
        void* pDecode = nullptr;
		unsigned char data[1024*4] = {0};
		fl = fopen(bEncodeX264?"encode.h264":"encode.h265","rb");
		BeginDecode(&pDecode,nullptr,bEncodeX264?27:173,[](void* obj, unsigned char* image_data, int& image_len,int frame_index){
            printf("--------------%d\r\n",frame_index);
			fflush(stdout);
            std::string file_name = std::string(".\\img\\image_")+std::to_string(frame_index)+std::string(".bmp");
            cv::Mat image = cv::Mat(height,width,CV_8UC(channel),image_data);
            cv::imwrite(file_name,image);
        });
		while (fl!=nullptr)
		{
			size_t len = fread(data, 1, sizeof(data), fl);
			ImageDecode(&pDecode,data, std::min(len,sizeof(data)));
			if (len < sizeof(data))	{
				break;
			}
		}
		EndDecode(&pDecode);
		fclose(fl);
		#pragma endregion
	}
	else if(strcmp(argv[1],"4")==0)
	{
		unsigned char buf[1024];
		void *pHandle = nullptr, *pHandle_Trans = nullptr;
		//FILE* fff = fopen("encode2.h264","wb");
		fl = fopen(bEncodeX264?"encode.h264":"encode.h265", "rb");
		BeginMuxing(&pHandle,"encode2.mp4",width,height,framerate,bitrate,2,false);
		BeginTranscode(&pHandle_Trans,pHandle,width,height,framerate,bEncodeX264?27:173,2,[](void* obj, unsigned char* data, int& len){
			Muxing(&obj,data,len);
			//fwrite(data,1,len,(FILE*)obj);
		});
		fseek(fl,0,0);
		while(feof(fl)==0){
			int rlen = fread(buf,1,1024,fl);
			Transcode(&pHandle_Trans,buf,std::min(1024,rlen));
		}
		EndTranscode(&pHandle_Trans);
		EndMuxing(&pHandle);
		//fclose(fff);
		fclose(fl);
	}
	else if(strcmp(argv[1],"5")==0)
	{
		// void* pHandle = nullptr;
		// fl = fopen(bEncodeX264?"encode.h264":"encode.h265", "wb");
		// cv::Mat image = cv::Mat::zeros(height,width,CV_8UC(channel));
		// MfxBeginEncode(&pHandle,nullptr,width,height,25,bitrate,bEncodeX264?27:173,[](void* obj, unsigned char* data, int& len){
		// 	static int i=0;
		// 	printf("------------%d\r\n",i++);
		// 	fwrite(data,1,len,fl);
		// 	fflush(stdout);
		// });
		// for(int i=1;i<25*4;i++){
		// 	std::string file = std::string("img\\image_")+std::to_string(i%250)+std::string(".bmp");
		// 	cv::Mat img = cv::imread(file.c_str(),-1);
		// 	if(img.dims == 0) {
		// 		printf("@");
		// 		fflush(stdout);
		// 		generateBitmap(image,i);
		// 		MfxImageEncode(&pHandle,image.data,image.cols*image.rows*image.elemSize());
		// 	}
		// 	else
		// 		MfxImageEncode(&pHandle,img.data,img.cols*img.rows*img.elemSize());
		// }
		// MfxEndEncode(&pHandle);
	}
	std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
	std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
	std::cout << "It took me " << time_span.count() << " seconds."<<std::endl;
	return 0;
}
#endif